﻿using XUCore.WeChat.Apis.Sns;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
using XUCore.Helpers;
using XUCore.Extensions;
using XUCore.WeChat.Enterprise.Apis.Sns;

namespace XUCore.WeChat.Enterprise.Net
{
    /// <summary>
    /// 企业微信网页授权筛选器
    /// </summary>
    public class EnterpriseWeChatOAuthFilter : AuthorizeAttribute, IAsyncAuthorizationFilter
    {
        private readonly string _state = "enterprise.wechat";

        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            IServiceProvider serviceProvider = context.HttpContext.RequestServices;
            ILogger<EnterpriseWeChatOAuthFilter> logger = serviceProvider.GetRequiredService<ILogger<EnterpriseWeChatOAuthFilter>>();

            logger.LogDebug($"EnterpriseWeChatOAuthFilter Begin {context.HttpContext.Request.Path}");

            //企业微信授权，企业成员和非企业成员二者只能取其一
            if (
                context.HttpContext.Request.Cookies.ContainsKey(EnterpriseWeChatConsts.COOKIE_ENTERPRISE_USERID) ||
                context.HttpContext.Request.Cookies.ContainsKey(EnterpriseWeChatConsts.COOKIE_ENTERPRISE_OPENID)
            )
            {
                return;
            }

            HttpRequest request = context.HttpContext.Request;

            string code = request.Query["code"].SafeString();
            string state = request.Query["state"].SafeString();

            string suiteId = request.Query["suiteid"].SafeString();

            //appid 则是 corpid
            string corpid = request.Query["appid"].SafeString();
            if (corpid.IsEmpty())
                corpid = request.Query["corpid"].SafeString();

            if (corpid.IsEmpty())
                throw new WeChatSdkException("corpid 或 appid 不可为空");

            int agentid = request.Query["agentid"].SafeString().ToInt();

            if (agentid <= 0)
                throw new WeChatSdkException("agentid 不可为空");

            //TODO:验证Token，过期自动刷新

            #region 如果是从企业微信验证页面跳转回来，根据Code和State拿到OpenId等信息

            if (!string.IsNullOrEmpty(code) && !string.IsNullOrEmpty(state))
            {
                logger.LogDebug($"从企业微信验证页面跳转回来... code:{code}\tstate:{state}");

                var tokenManager = serviceProvider.GetRequiredService<IEnterpriseWeChatTokenManager>();
                var token = await tokenManager.GetAccessTokenAsync(suiteId, corpid, agentid);

                var weChatFuncs = serviceProvider.GetRequiredService<EnterpriseWeChatFuncs>();

                var snsApi = serviceProvider.GetRequiredService<IEnterpriseSnsApi>();
                (var _, var _, var agent) = weChatFuncs.GetEnterpriseWeChatAgentOptions(suiteId, corpid, Conv.ToInt(agentid));

                //通过code换取access_token,Code只能用一次
                var userinfo = await snsApi.GetUserInfoAsync(token, code);

                logger.LogDebug($"AccessToken:{token}");

                IResponseCookies cookies = context.HttpContext.Response.Cookies;

                if (userinfo.userid.NotEmpty())
                {
                    cookies.Append(EnterpriseWeChatConsts.COOKIE_ENTERPRISE_USERID, userinfo.userid, new CookieOptions()
                    {
                        Path = "/",
                        Expires = DateTimeOffset.Now.AddDays(30),
                        HttpOnly = true,
                        IsEssential = true,
                    });
                    context.HttpContext.Items[EnterpriseWeChatConsts.COOKIE_ENTERPRISE_USERID] = userinfo.userid;
                }

                if (userinfo.user_ticket.NotEmpty())
                {
                    cookies.Append(EnterpriseWeChatConsts.COOKIE_ENTERPRISE_WEBTICKET, userinfo.user_ticket, new CookieOptions()
                    {
                        Path = "/",
                        Expires = DateTimeOffset.Now.AddSeconds(1800),
                        HttpOnly = true,
                        IsEssential = true,
                    });
                    context.HttpContext.Items[EnterpriseWeChatConsts.COOKIE_ENTERPRISE_WEBTICKET] = userinfo.user_ticket;
                }

                if (userinfo.openid.NotEmpty())
                {
                    cookies.Append(EnterpriseWeChatConsts.COOKIE_ENTERPRISE_OPENID, userinfo.openid, new CookieOptions()
                    {
                        Path = "/",
                        Expires = DateTimeOffset.Now.AddDays(30),
                        HttpOnly = true,
                        IsEssential = true,
                    });
                    context.HttpContext.Items[EnterpriseWeChatConsts.COOKIE_ENTERPRISE_OPENID] = userinfo.openid;
                }

                if (userinfo.external_userid.NotEmpty())
                {
                    cookies.Append(EnterpriseWeChatConsts.COOKIE_ENTERPRISE_EXTERNALUSERID, userinfo.external_userid, new CookieOptions()
                    {
                        Path = "/",
                        Expires = DateTimeOffset.Now.AddDays(30),
                        HttpOnly = true,
                        IsEssential = true,
                    });
                    context.HttpContext.Items[EnterpriseWeChatConsts.COOKIE_ENTERPRISE_EXTERNALUSERID] = userinfo.external_userid;
                }

                logger.LogDebug("企业微信网页授权完成...");

                return;
            }

            #endregion 如果是从企业微信验证页面跳转回来，根据Code和State拿到OpenId等信息

            else if (
                !context.HttpContext.Request.Cookies.ContainsKey(EnterpriseWeChatConsts.COOKIE_ENTERPRISE_USERID) ||
                !context.HttpContext.Request.Cookies.ContainsKey(EnterpriseWeChatConsts.COOKIE_ENTERPRISE_OPENID))
            {
                string redirectUrl = GetRedirectUrl(context.HttpContext);

                var weChatFuncs = serviceProvider.GetRequiredService<EnterpriseWeChatFuncs>();
                (var _, var _, var agent) = weChatFuncs.GetEnterpriseWeChatAgentOptions(suiteId, corpid, Conv.ToInt(agentid));

                //获取授权Url
                string url = WeChatHelper.GetEnterpriseAuthorizeUrl(redirectUrl, _state, corpid, agent.AgentId, OAuthScopes.snsapi_privateinfo);

                logger.LogDebug($"跳转至企业微信服务器获取授权...{Environment.NewLine}RedirectUrl：{redirectUrl}{Environment.NewLine}AuthUrl:{url}");

                context.Result = new RedirectResult(url);
            }
            else
            {
                logger.LogError($"授权出错，请检查...{request.Path}");
                context.Result = new ContentResult { Content = "授权出错，请检查！" };
            }
        }

        /// <summary>
        /// 获取当前URL
        /// </summary>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        public virtual string GetRedirectUrl(HttpContext httpContext)
        {
            HttpRequest request = httpContext.Request;

            string redirectUrl = UriHelper.GetDisplayUrl(request);

            return redirectUrl;
        }
    }
}